package WizardTD.element;

import WizardTD.App;
import WizardTD.board.ManaProcessBar;
import WizardTD.constant.Constant;
import WizardTD.constant.ImageConstant;
import lombok.Data;
import processing.core.PApplet;
import processing.core.PConstants;
import processing.core.PImage;
import processing.core.PVector;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Data
public class Tower extends Element {

    public Map<String, Integer> levelMap = new HashMap<>();

    public boolean isChoose = false;

    public boolean shootFlag = false;

    private PImage image;
    private int towerCost;
    private float range;
    private float speed;
    private float damage;
    //当前攻击的怪物
    private Monster monster;

    //累计
    private int count = 30;


    public Tower(float coordinateX, float coordinateY) {
        super(coordinateX, coordinateY);
        this.damage = Constant.initialTowerDamage;
        this.range = Constant.initialTowerRange;
        this.speed = Constant.initialTowerFiringSpeed;
        this.image = ImageConstant.tower0;
        App.board.getManaProcessBar().subMana(20);
    }

    public boolean upgrade(String upgradeType) {
        if (levelMap.getOrDefault(upgradeType, 0) >= 3) return false;
        ManaProcessBar mana = App.board.getManaProcessBar();
        switch (upgradeType) {
            case "range": {
                range += 32;
                break;
            }
            case "U2": {
                speed += 0.5;
                break;
            }
            case "U3": {
                damage += 0.5 * Constant.initialTowerDamage;
                break;
            }
        }
        mana.subMana(20 + 10 * levelMap.getOrDefault(upgradeType, 0));
        levelMap.put(upgradeType, levelMap.getOrDefault(upgradeType, 0) + 1);
        return true;
    }

    public Fireball createBullet() {
        float x = this.getCoordinateX();
        float y = this.getCoordinateY();
        Fireball fireball = new Fireball(x + 16, y + 16, monster, damage);
        return fireball;
    }

    @Override
    public void draw(PApplet pApplet) {
        count++;
        drawByLevel(pApplet);
        float x = this.getCoordinateX() + 16;
        float y = this.getCoordinateY() + 16;
        //被选中显示攻击范围
        if (isChoose) {
            pApplet.noFill();
            pApplet.stroke(255,255,0);
            pApplet.arc(x, y, this.range * 2, this.range * 2, 0, PConstants.TWO_PI);
            pApplet.stroke(0,0,0);
        }
        //Fireball生成
        if (count >= (60 * speed) && shootFlag) {
            count = 0;
            Fireball bullet = createBullet();
            App.fireballs.add(bullet);
        }
    }

    private void drawByLevel(PApplet pApplet) {
        float x = this.getCoordinateX();
        float y = this.getCoordinateY();
        int rangeLevel = levelMap.getOrDefault("range", 0);
        int damageLevel = levelMap.getOrDefault("damage", 0);
        int speedLevel = levelMap.getOrDefault("speed", 0);

        int basic = 0;
        PImage pImage = ImageConstant.tower0;

        if (rangeLevel >= 1 && damageLevel >= 1 && speedLevel >= 1) {
            basic = 1;
            pImage = ImageConstant.tower1;
        }
        if (rangeLevel >= 2 && damageLevel >= 2 && speedLevel >= 2) {
            basic = 2;
            pImage = ImageConstant.tower2;
        }
        pApplet.image(pImage, x, y);
        float rangeX = x;
        int i = 0;
        while (i++ < rangeLevel - basic) {
            pApplet.fill(128,0,0);
            pApplet.text("O",rangeX, y + 8);
            rangeX += 8;
        }
        float damageX = x;
        i = 0;
        while (i++ < damageLevel - basic) {
            pApplet.fill(128,0,0);
            pApplet.text("X",damageX, y +  32);
            damageX += 8;
        }

        if ((speedLevel - basic) > 0) {
            pApplet.strokeWeight((speedLevel - basic) * 2);
            pApplet.stroke(51, 102, 255);
            pApplet.line(x + 8, y + 8, x + 24, y + 8);
            pApplet.line(x + 8, y + 8, x + 8, y + 24);
            pApplet.line(x + 24, y + 24, x + 24, y + 8);
            pApplet.line(x + 24, y + 24, x + 8, y + 24);
            pApplet.stroke(0, 0, 0);
            pApplet.strokeWeight(1);
        }
    }

    public boolean decideShoot(List<Monster> monsters) {
        PVector tp = new PVector(this.getCoordinateX(), this.getCoordinateY());
        float r = this.range;
        for (Monster m : monsters) {
            PVector mp = new PVector(m.getCoordinateX() + 10, m.getCoordinateY() + 10);
            if (mp.sub(tp).mag() <= r + 10) {
                this.monster = m;
                return true;
            }
        }
        this.monster = null;
        return false;
    }
}
